home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magnum One
/
Magnum One (Mid-American Digital) (Disc Manufacturing).iso
/
d12
/
asmbler.arc
/
NFIND.ASM
< prev
next >
Wrap
Assembly Source File
|
1988-11-19
|
38KB
|
878 lines
COMMENT &
XFIND Filter
Command
-------------------------------------------------------------------------
Purpose: This filter sends to the standard output device all
lines from the filenames specified in the command line
that contain the specified string. Letter case is
IGNORED in the comparisons, unless an exact match is
requested by the /E switch. Command line parameters may
be separated by one or more blanks, tabs, or commas.
Format: XFIND [/C] [/E] [/N] [/V] "pat" [[d:][path]filename[.ext]...]
Type: Internal External
***
Remarks: The search is restricted to strings found in a single
lines. Patterns split across line boundaries will not
be recognized.
The /C parameter causes XFIND to display only a count of
the number of matching occurrences of string in each
file, without displaying the matching lines from the
file.
The /E parameter requests an exact match with respect to
letter case in the string.
The /N parameter causes the relative line number of each
matching line to be displayed ahead of the line from the
file.
The /V parameter causes all lines NOT containing the
string to be displayed.
The string must be enclosed in double quotes. Two
quotes in succession are taken as a single quote.
Unlike FIND, global filename characters ARE allowed in
the filenames or extensions, but alas, due to DOS
2.0 limitations, not in directory paths.
Examples:
XFIND /C "equ" *.asm ! Count the number of equ's
XFIND "foobar" *.for,*.asm,*.pas
xfind /e "Tel:" phone1 phone2 ph*.txt phone3
Error returns: 0 - success
1 - empty pattern
2 - command line incomplete
3 - one or more file open failures (some output may be
produced)
4 - file not found in wildcard expansion
5 - file read error
-------------------------------------------------------------------------
The code has been developed from a disassembly of the IBM PC FIND Filter
command.
The 8088 has single instructions for scanning a string for an exact
match or mismatch with a single character, but none for doing this with
translation. Using translation turns one of these instructions into a
5-instruction loop with 5 entry/exit instructions, and the other becomes
a 9-instruction loop with 4 entry/exit instructions. A test in a large
file directory showed this routine to be about 15% slower than the FIND
utility (87 sec vs 77 sec), which is not an unacceptable overhead.
[03-Feb-84] Nelson H.F. Beebe, University of Utah
[01-Mar-84] Brad Davis, Drafting Services Ltd, Salt Lake City, UT
(changed code to allow use as .COM file and have big
input buffer)
&
include ascii.inc
include dos.inc
MAXBUF equ 58*1024 ; Buffer size - freely variable within
; segment size limitation. Original value
; was 4096. Code takes 3K, leave 3K for stack
assume cs:findc,ds:findc,es:findc,ss:findc
findc segment para public 'code'
org 100H ; where a .COM file begins
start: jmp find ; jump around constant data
db "MAUlloa/Microsoft/V126"
colon db ':',' ' ; 16
linstr db '[' ; 18
intstr db 8 dup (0) ; 19
; Flags recording switch settings. These should be consecutive bytes.
; A value FLAGSET means the flag is set, any other means not set
FLAGSET equ -1 ; value signalling flag set
flags equ $ ; symbol used to index table
notflg db 0 ; /V
cntflg db 0 ; /C
numflg db 0 ; /N
exactflg db 0 ; /E
; return code flags in order of increasing severity. The highest
; met is returned
RC_OKAY equ 0 ; success
RC_PATT equ 1 ; empty pattern
RC_PARM equ 2 ; bad command line syntax
RC_FILE equ 3 ; file open failure
RC_NFND equ 4 ; file not found
RC_READ equ 5 ; file read error
rc db RC_OKAY ; return code
db 0,0 ; 24,25
matches dw ; 26
lineno dw ; 28
find: ; Begin main program
mov rc,RC_OKAY ; tentative return code
mov ah,$DOS_GETVERSION
int $DOS
cmp al,2 ; version 2 or later?
jge cont ; jump if yes
mov dx,offset baddos
mov ah,$DOS_STROUT ; print string
int $DOS
xor ax,ax ; clear ax
mov ah,$DOS_EXIT
int $DOS
assume cs:findc,ds:findc
cont: ; continue main program now that DOS
mov si,81h ; Address in PSP of command line
call skipsp ; Skip leading spaces
or bx,bx ; Test skip result, non-zero at CR
jz haveparam ; jump if have command line data
cnterr:
mov dx,offset numerr; error - need more parameters
mov cl,numlen ; message and message length in dx,cl
call writedserr ; write a message
mov al,RC_PARM ; return code
call setrc
jmp errexit ; abort
haveparam:
mov ah,$DOS_SWITCH ; get switchar (undocument internal call)
mov al,$DOS_SWITCH_GET
int $DOS
push dx ; save switch character
scanswitch: ; begin loop to scan for switches
lodsb ; get byte from [si] to al, increment si
cmp al,' ' ; blank?
je moresp ; jump if so to flush more space
cmp al,.HT ; tab?
je moresp ; jump if so to flush more space
cmp al,.CR ; end-of-line?
je cnterr ; jump if so -- error - need more data
pop dx ; restore switch character
cmp al,dl ; switch character?
jne scanpat ; jump if not - now expect to find "pattern"
push dx ; save switch character again
lodsb ; get byte from [si] to al, increment si
cmp al,' ' ; blank?
je moresp ; jump if so to flush more space
cmp al,.HT ; tab?
je moresp ; jump if so to flush more space
cmp al,.CR ; end-of-line?
je cnterr ; jump if so -- error - need more data
call lcuc ; convert to upper-case
mov bx,offset notflg
cmp al,'C' ; /C? (count matching lines only)
je setcnt ; jump if yes
cmp al,'E' ; /E? (exact match)
je setexact ; jump if yes
cmp al,'N' ; /N? (line numbers)
je setnum ; jump if yes
cmp al,'V' ; /V? (invert search)
je setnot ; jump if yes
mov pattrn[0],al ; unrecognized switch character
mov dx,offset prmerr; message
mov cl,prmlen ; and length
call writedserr ; go write it
mov dx,offset pattrn; NUL
mov cx,1 ; 1 character
call writedserr ; write the NUL
mov dx,offset crlf ; and a CR LF
mov cx,2
call writedserr
jmp scanswitch ; continue switch scan
setcnt: ; /C found
mov di,cntflg-flags ; offset in switch table
jmp short setflg ; go set it
setexact:
mov di,exactflg-flags ; offset in switch table
jmp short setflg ; go set it
setnum: ; /N found
mov di,numflg-flags ; offset in switch table
jmp short setflg ; go set it
setnot: ; /V found
mov di,notflg-flags ; offset in switch table
; fall through to setflg
setflg: ; set the switch
mov byte ptr [bx+di],FLAGSET
jmp scanswitch ; continue switch scan
moresp: ; flush white space in command line
dec si ; backup to space just found
call skipsp ; go skip some space
or bx,bx ; end-of-line reached?
jz scanswitch ; jump if not
jmp cnterr ; error - expected more data
scanpat: ; Begin code to scan "pattern"
cmp al,'"' ; Quote?
jne nopat ; Jump if not - error if no pattern
mov di,offset pattrn; where to store the pattern
xor cx,cx ; clear count of pattern length
patch:
lodsb ; get byte from [si] to al, increment si
cmp al,.CR ; end-of-line?
jne stlpat ; jump if not, still in pattern
nopat: ; here if pattern absent or incomplete
mov dx,offset synerr; message
mov cl,synlen ; and length
call writedserr ; write it
mov al,RC_PATT ; return code
call setrc
jmp errexit ; abort
stlpat: ; here if still in pattern
cmp al,'"' ; quote?
jne stoch ; jump if not to save character
lodsb ; get byte from [si] to al, increment si
cmp al,'"' ; pair of quotes?
je stoch ; yes, save only one of them
dec si ; no, must be end of pattern
mov patlen,cx ; save pattern length
or cx,cx ; was it zero?
jnz havpat ; jump if not, have valid pattern
mov al,RC_PATT ; return code for empty pattern
call setrc
jmp errexit ; abort
stoch: ; store pattern character
stosb ; store byte in al at [di], increment di
inc cx ; count the character
jmp patch ; go back for more
havpat:
call skipsp ; flush more white space
or bx,bx ; end-of-line yet?
jz havfil ; no, expect filename(s) now
mov ax,$STDIN ; no file names, so use standard input
jmp doread ; go begin the read of the file
havfil: ; Begin scan for filename(s)
call clrcnt ; go zero some counts
mov di,offset filnam; where to store the filename
xor cx,cx ; clear the filename length count
filch: ; loop to collect the next filename
lodsb ; get byte from [si] to al, increment si
cmp al,' ' ; blank?
je filend ; jump if so, have a filename
cmp al,.HT ; tab?
je filend ; jump if so, have a filename
cmp al,.COMMA ; comma?
je filend ; jump if so, have a filename
cmp al,.CR ; end-of-line?
je filend ; jump if so, have a filename
stosb ; must be filename character, save it
inc cx ; and count it
jmp filch ; loop back for more
filend: ; here when filename collected
dec si ; backup to terminator character after name
mov byte ptr [di],.NUL ; replace terminator by NUL
push si ; save registers so we can scan for the
mov fillen,cx ; save name length
mov dx,offset fildta
mov ah,$DOS_SETDTA
int $DOS ; set new disk transfer area
mov cx,0 ; attribute flags - find only normal files
mov dx,offset filnam ; address of wild-carded filename
mov ah,$DOS_FINDFIRST
int $DOS ; find first matching file
jmp short file00 ; go check error return
filenext: ; here to find next matching file
mov ah,$DOS_FINDNEXT
int $DOS ; find next matching file
file00: ; here to check error return of FINDFIRST
; or FINDNEXT
jnb filmak ; jump if carry not set
; find file failed -- test error code returned in ax
file01: cmp ax,18 ; no more files?
jne file02 ; jump if not "no more files" condition
jmp nxtfil ; no more files from this expansion
file02:
cmp ax,2 ; file not found?
jne file03 ; jump if other error
mov al,RC_NFND ; "file not found" error
call setrc
jmp nxtfil
file03: ; some other undocumented error
mov al,RC_FILE
call setrc
jmp nxtfil
filmak: ; here after matching file found
call makefile ; go attach path to name
mov dx,offset fpath ; address of the full filename
mov ah,$DOS_OPEN2
mov al,$DOS_OPEN2_READ
int $DOS ; open the file for input
jnb filopn ; jump if carry not set, open okay
jmp badfil ; carry set, open failed
filopn: ; here after file opened (ax=handle)
push ax ; save file handle
mov dx,offset seplin; address of separator line
mov cl,seplen ; and its length
xor ch,ch ; clear top half of cx
call writestr ; write separator line
mov dx,offset fpath ; address of filename
mov cx,fpalen ; and its length
call writestr ; append filename to separator line
cmp cntflg,FLAGSET ; was /C specified?
je nocrlf ; jump if yes - will only write count
mov dx,offset crlf ; else output CR LF
mov cx,2
call writestr
nocrlf:
pop ax ; restore file handle
doread: ; here to read the open file
mov bx,ax ; file handle
nxtread: ; here for next block of file
mov dx,offset buffer; where to put block
mov cx,MAXBUF ; how long it is
mov ah,$DOS_READ2
int $DOS ; read the block
jnb didread ; jump if carry not set, read okay
jmp badread ; carry set on error
didread:
or ax,ax ; test count of bytes read
jnz grepbuf ; if non-zero, go do pattern match
cmp cntflg,FLAGSET ; end-of-file, was /C specified?
jne nocnt ; no, all done on this file
call writecnt ; yes, write the count of matches
nocnt:
cmp bx,$STDIN ; input from standard input file?
jne doclose ; jump if not and close the file
jmp nrmexit ; yes, no need to close, and all done
doclose: ; here to close the file (handle in bx)
mov ah,$DOS_CLOSE2
int $DOS ; close the file
jmp filenext ; and go for next one in wild list
grepbuf: ; here to search block for pattern
push bx ; save file handle
mov bp,offset buffer; where the block is
mov di,ax ; count of bytes in block
cmp ax,MAXBUF ; block full?
jge nopatch ; jump if yes
mov bx,bp ; partial block, get address of block
cmp byte ptr [bx+di-01],.LF ; is last character LF?
je nopatch ; yes
mov byte ptr [bx+di],.CR ; no, append CR LF at end of file
inc di ; when it is missing, since
mov byte ptr [bx+di],.LF ; the search algorithm expects this
inc di ; terminator
nopatch:
push di ; save count of bytes in block
push bp ; save block address
mov dx,patlen ; pattern length
dec dx ; pattern length - 1
nxtscn:
inc lineno ; increment line number
pop bp ; block address
mov di,bp
pop cx ; count of bytes in block
mov bx,cx
mov al,.LF
jcxz nofulln ; jump if no more bytes in block
repnz scasb ; search for LF marking end-of-line
jne nofulln ; jump if no end-of-line in block
push cx ; save count of bytes remaining
push di ; and location of end-of-line
mov cx,di ; where LF is in block
sub cx,bp ; compute length of line
mov bx,cx ; save length of line
dec cx ; then reduce for CR
dec cx ; and LF
jcxz notfnd ; jump if line is empty
mov di,bp ; address of line in block
samln: ; Loop to scan single line for pattern
mov si,offset pattrn
lodsb ; get byte from [si] to al, increment si
cmp exactflg,FLAGSET; /E specified?
je sam01 ; jump if yes
call xnzscasb ; search for pattern byte, ignoring case
jmp short sam02
sam01:
repnz scasb ; search for exact match with pattern byte
sam02:
jnz notfnd ; jump if byte not found
cmp cx,dx ; found byte, is line longer than pattern?
jb notfnd ; jump if not, not acceptable match
push di ; save block address
push cx ; and length of line
mov cx,dx ; remaining length of pattern
jcxz didfnd ; jump if pattern exhausted
cmp exactflg,FLAGSET; /E specified?
je sam03 ; jump if yes
call xzcmpsb ; compare rest of pattern with current source
jmp short sam04
sam03:
repz cmpsb ; compare for exact match
sam04:
je didfnd ; jump if found string match
pop cx ; no match, restore old count
pop di ; and source index
jmp samln ; and go continue source scan
didfnd: ; here when pattern found
pop ax ; discard block address
pop ax ; and line length on stack
cmp notflg,FLAGSET ; was /V specified?
jne negnot ; jump if not
jmp nxtscn ; pattern found and /V says list non-matching
; lines, so go search on next line
notfnd: ; here when pattern not found on current line
cmp notflg,FLAGSET ; was /V specified?
jne nxtscn ; jump if not
negnot: ; here when (/V AND pattern NOT found) OR
; (NOT /V AND pattern found), i.e. matched
cmp cntflg,FLAGSET ; was /C specified?
jne nocount ; jump if not
inc matches ; had /C, so increment pattern match count
jmp nxtscn ; and go search next line
nocount: ; here on match when line is to be printed
push dx ; save dx (remaining length of pattern)
cmp numflg,FLAGSET ; was /N specified?
jne nolnnum ; jump if not
call writelnnum ; had /N, write line number
nolnnum: ; here after possibly writing line number
mov dx,bp ; address of line in block
mov cx,bx ; length of line
call writestr ; go write matching line
pop dx ; restore dx
jmp nxtscn ; go search next line
nofulln: ; here when line split across blocks;
; the input file pointer must be backed
; up to the beginning of the current line
mov dx,bx ; length of line
pop bx ; file handle
or dx,dx ; test line length
jz nxtblock ; jump if 0
neg dx ; -(length of line)
mov cx,-1 ; (cx,dx) = file offset
mov al,$DOS_LSEEK_CURRENT
mov ah,$DOS_LSEEK
int $DOS ; reposition to beginning of current line
jc badread ; abort if lseek failed
nxtblock:
jmp nxtread ; go for next block
badread: ; here on lseek/read failure
mov al,RC_READ ; return code
call setrc
bad01:
cmp bx,$STDIN ; reading standard input?
jne bad02 ; jump if not
jmp nrmexit ; yes, all done
bad02:
mov ah,$DOS_CLOSE2 ; no, close the file
int $DOS
mov dx,offset rdderr; error message
mov cl,rddlen ; and length
jmp dowrite ; write message
badfil: ; here on open failure
mov dx,offset fnderr; error message
mov cl,fndlen ; and length
mov al,RC_FILE ; return code
call setrc
dowrite: ; here to print error message and file name
call writeerr
call writefil
nxtfil: ; here to find next file on command line
pop si ; address of last byte examined
call skipsp ; flush white space
or bx,bx ; end-of-line reached?
jnz nrmexit ; yes, all done
jmp havfil ; no, go collect file name
setrc: ; routine to set return code from al
cmp al,rc ; higher than current one?
jbe setrc1 ; jump if not
mov rc,al ; else save new one
setrc1:
ret ; return to caller
; routine to build a full filename in fpath (terminated by NUL)
; from wild-carded path in filnam and filename in fname, since
; FINDFIRST/FINDNEXT do not return a complete file spec
makefile:
push ax ; save registers
push cx
push si
push di
mov di,offset fpath ; where full file spec is to go
mov si,offset filnam; where wild card spec is
cld ; clear direction flag for positive increment
push di ; save separator address+1
; Copy filnam (up to last non-NUL) into fpath, remembering location
; of last separator (:/\) so we can append fname to it. DOS should
; have done this!!! Note that this omission prevents wildcarding
; directory names, since there is no way to determine the directory
; name when only the file name is returned by FINDFIRST/FINDNEXT
make01: ; loop copying filnam into fpath
lodsb ; source byte to al, increment si
cmp al,.NUL ; end-of-string?
je make03 ; yes, all done
stosb ; no, store byte in al to [di], increment di
cmp al,':' ; device separator?
je make02 ; jump if separator
cmp al,'\' ; path separator?
je make02 ; jump if so
cmp al,'/' ; alternate path separator?
je make02 ; jump if so
jmp short make01 ; loop for next character
make02:
pop ax ; discard old address
push di ; remember separator address (+1)
jmp short make01 ; loop for more
make03: ; here at end-of-string. fpath now has
; copy of filnam (wild-carded spec)
pop di ; address of last separator+1
mov si,offset fname
make04: ; loop copying fname into fpath after term.
lodsb ; byte from [si] to al, increment si
stosb ; byte from al to [di], increment di
cmp al,.NUL ; end-of-string yet?
jne make04 ; loop if more
xor cx,cx ; clear count
mov si,offset fpath ; address of fpath
make05:
lodsb ; loop counting characters
cmp al,.NUL ; end-of-string yet?
je make06 ; yes
inc cx ; no, count the character
jmp short make05 ; loop for more
make06:
mov fpalen,cx ; save fpath length
pop di ; restore registers saved at entry
pop si
pop cx
pop ax
ret ; return to caller
errexit: ; here for error exit
cmp rc,RC_PARM ; bad parameter?
je erruse ; yes, print usage message
cmp rc,RC_PATT ; bad
je erruse ; yes, print usage message
jmp nrmexit ; else just exit
erruse: ; here to print usage message
mov dx,offset useerr; message address
mov cl,uselen ; and length
call writedserr
nrmexit: ; here to exit to DOS when done
mov al,rc ; set return code
mov ah,$DOS_EXIT
int $DOS ; exit to DOS
skipsp: ; routine to skip white space on command line
cld ; clear direction flag to increment si
xor bx,bx ; clear end-of-line flag returned in bx
havesp: ; loop skipping white space
lodsb ; get byte from [si] to al, increment si
cmp al,' ' ; blank?
je havesp ; yes, keep looping
cmp al,.HT ; tab?
je havesp ; yes, keep looping
cmp al,.COMMA ; comma
je havesp ; yes, keep looping
cmp al,.CR ; end-of-line?
jne nocr ; jump if not - hit non-white space character
mov bx,ax ; end-of-line hit, set return flag non-zero
nocr:
dec si ; backup to last white space character
ret ; return to caller with bx set to flag
clrcnt: ; routine to clear search counts
mov byte ptr matches,0 ; clear match count
mov byte ptr lineno,0 ; and line number
ret
writecnt: ; routine to write count
push bx ; save file handle
cmp bx,$STDIN ; standard input?
je nocolon ; jump if yes (no file name output)
mov dx,offset colon ; no, follow file name by colon
mov cx,2 ; string length
call writestr ; write the colon
nocolon:
mov ax,matches ; count of matches
mov di,offset intstr; message
call writeint ; write the integer
mov dx,offset intstr; message
call writestr ; write the message
mov dx,offset crlf ; and follow it by
mov cx,2 ; a CR LF
call writestr
pop bx ; restore the file handle
ret ; return to caller
writelnnum: ; here to write a line number
push bx ; save file handle
push dx ; and remaining pattern length
mov ax,lineno ; line count
mov di,offset intstr; message
call writeint ; write the integer
mov byte ptr [di],']' ; follow it by left square bracket
inc cx
inc cx ; increment count by 2
mov dx,offset linstr; address of string
call writestr ; write [nnnn] string
pop dx ; restore pattern length
pop bx ; and file handle
ret
writestr: ; routine to write string at ds:dx,length in cx
mov bx,$STDOUT
mov ah,$DOS_WRITE2
int $DOS
ret
writeint: ; routine to format integer in ax to [di]
mov bx,10
xor cx,cx ; clear count of bytes written
intdiv:
inc cx ; increment count of bytes written
cmp ax,bx ; remainder < 10?
jb intdone ; jump if yes, have only single digit left
xor dx,dx ; clear dx (top half of 32-bit numerator)
div bx ; (ax,dx)/10 to ax, (ax,dx) mod 10 to dx
add dl,'0' ; make into ASCII digit
push dx ; save on stack
jmp intdiv ; keep collecting digits
intdone:
add al,'0' ; make into ASCII digit
push ax ; save on stack
mov bx,cx ; save count of digits
intsto: ; loop to pull digits from stack
pop ax ; get a digit
stosb ; store in target string
loop intsto ; loop while cx > 0
mov cx,bx ; count of digits
ret ; return to caller
writefil: ; routine to write file name and CR LF
mov dx,offset fpath ; full filename
mov cx,fpalen ; and length
call writeerr ; write it
mov dx,offset crlf
mov cx,2
call writeerr ; write CR LF
ret ; return to caller
writedserr: ; routine to write error message from ds:
call writeerr
ret
writeerr: ; routine to write error message
xor ch,ch
mov bx,$STDERR
mov ah,$DOS_WRITE2
int $DOS
ret
lcuc: ; routine to convert al to upper-case
cmp al,'a' ; less than 'a'
jb ok ; yes, cannot be lower-case
cmp al,'z' ; greater than 'z'
jg ok ; yes, cannot be lower-case
and al,not 20h ; turn off lc bit
ok:
ret ; return to caller
;
; Begin translated equivalent of REPNZ SCASB
;
xnzscasb:
push ax ; save ax and
push bx ; bx during this loop
mov bx, offset xtable
xlat byte ptr xtable ; al <- xtable(al) - translated pattern byte
mov ah,al ; translated pattern byte
loop1:
mov al,es:byte ptr [di] ; source byte
xlat byte ptr xtable ; translate source byte in al
inc di ; point to next byte (like scasb does)
cmp ah,al ; source = pattern?
loopne loop1 ; decrement cx and loop while no match
pop bx ; restore bx
pop ax ; and ax
ret
;
; End translated equivalent of REPNZ SCASB
;
;
; Begin translated equivalent of REPZ CMPSB
;
xzcmpsb:
push ax ; save ax and
push bx ; bx during this loop
mov bx, offset xtable
loop2:
mov al,byte ptr [si];pattern byte
xlat byte ptr xtable ; al <- xtable(al) - translated pattern byte
mov ah,al ; translated pattern byte
mov al,es:byte ptr [di] ; source byte
xlat byte ptr xtable ; translate source byte in al
inc si ; point to next byte (like cmpsb does)
inc di ; point to next byte (like cmpsb does)
cmp ah,al ; source = pattern?
loope loop2 ; decrement cx and loop while match
pop bx ; restore bx
pop ax ; and ax
ret
;
; End translated equivalent of REPZ CMPSB
;
xtable equ $ ; translation table mapping lower case into upper
xbyte=0
rept 97 ; NUL .. "`" --> themselves
db xbyte
xbyte=xbyte+1
endm
xbyte=65
rept 26 ; "a".."z" --> "A".."Z"
db xbyte
xbyte=xbyte+1
endm
xbyte=123
rept 133 ; "["..0FFH --> themselves
db xbyte
xbyte=xbyte+1
endm
patlen dw ; 0332
pattrn db 128 dup (0) ; 0334
fillen dw ; 03b4
filnam db 65 dup (0) ; 03b6
db 9 dup (0)
; file disk transfer area for wild-card expansion
even
fildta db 21 dup (?) ; reserved for DOS
db 0 ; attribute found - 0 means only normal files
dw ? ; file's time
dw ? ; file's date
dw ? ; low word of file size
dw ? ; high word of file size
fname db 13 dup (?) ; file name (asciz string)
; end of file disk transfer area
fpalen dw 0 ; length of fpath (up to before NUL)
fpath db 65 dup (0) ; space for expanded file name from dta
baddos db "Incorrect DOS version$" ; 00
crlf db .CR,.LF ; 16
numerr db "XFIND: Invalid number of parameters",.CR,.LF ; 18
numlen db numlen-numerr ; 3C
synerr db "XFIND: Syntax error",.CR,.LF ; 3D
synlen db synlen-synerr ; 51
fnderr db "XFIND: File not found " ; 52
fndlen db fndlen-fnderr ; 67
rdderr db "XFIND: Read error in " ; 68
rddlen db rddlen-rdderr ; 7C
prmerr db "XFIND: Invalid Parameter " ; 7D
prmlen db prmlen-prmerr ; 95
useerr db "Usage: XFIND [/C] [/E] [/N] [/V] "
db '"string"" [[d:][path]filename[.ext] [,]]',.CR,.LF
db "/C : match count only",.CR,.LF
db "/E : exact match with respect to letter case required",.CR,.LF
db "/N : print line numbers of matching lines",.CR,.LF
db "/V : invert match - display lines NOT containing pattern"
db .CR,.LF
uselen db uselen-useerr
seplin db .CR,.LF,"---------- " ; 96
seplen db SEPLEN-SEPLIN ; A3
if ($-findc) mod 256
org ($-findc)+256-(($-findc) mod 256) ; Start buffer on 256n
; boundary
endif
buffer EQU THIS BYTE ; There must be space for MAXBUF dup (?)
; here, plus some more on top for the
; stack. This trick is used instead of
; MAXBUF dup (?) because even with
; initialization to (?), LINK creates a
; .EXE file proportionate in size to
; this value...baahhh!!!
findc ends
end start